home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000…tember: Reference Library / Dev.CD Sep 00 RL Disk 1.toast / mac / Technical Documentation / Develop / develop Issue 21 / develop Issue 21 code / OpenDoc Graphics Recipes < prev   
Encoding:
Text File  |  1995-01-16  |  13.0 KB  |  402 lines  |  [TEXT/ttxt]

  1. // Listing 1. MyPart::Draw, simplest case
  2. void MyPart::Draw(Environment* ev, ODFacet* facet, ODShape* invalShape)
  3. {
  4.     // Set up graphics port.
  5.     GrafPtr port = facet->GetCanvas(ev)->GetQDPort(ev);
  6.     SetPort(port);
  7.  
  8.     // Set up graphics port offset for drawing content.
  9.     ODTransform* localToGlobal = facet->GetContentTransform(ev, kODNULL);
  10.     ODPoint offset(0,0);
  11.     offset = localToGlobal->TransformPoint(ev, &offset);
  12.     SetOrigin(-offset.IntX(), -offset.IntY());
  13.     localToGlobal->Release(ev);
  14.  
  15.     // Set up graphics port clip; save old clip.
  16.     RgnHandle saveClip = NewRgn();
  17.     GetClip(saveClip);
  18.     ODShape* clipShape = facet->GetAggregateClipShape(ev, kODNULL);
  19.     RgnHandle clip = clipShape->GetQDRegion(ev);
  20.     SetClip(clip);
  21.     clipShape->Release(ev);
  22.  
  23.     // And draw (insert your drawing code here).
  24.     // Remember to respect the scaling and rotation information
  25.     // in your content transform, if possible. If you can't do this,
  26.     // it's graceful to at least try to draw as best you can, rather
  27.     // than simply signaling an error.
  28.     ...
  29.  
  30.     // Clean up.
  31.     SetClip(saveClip);
  32.     DisposeRgn(saveClip);
  33.     SetOrigin(0,0);
  34. }
  35.  
  36. // Listing 2. MyPart::Draw, with scrolling
  37. void MyPart::Draw(Environment* ev, ODFacet* facet, ODShape* invalShape)
  38. {
  39.     Point        spclOffset = {0,0};
  40.     Point        contentOffset = {0,0};
  41.     
  42.     // Set up graphics port.
  43.     GrafPtr port = facet->GetCanvas(ev)->GetQDPort(ev);
  44.     SetPort(port);
  45.  
  46.     // Set up graphics port offsets for controls.
  47.     ODTransform* localToGlobal = facet->GetFrameTransform(ev, kODNULL);
  48.     ODPoint tempOffset1(0,0);
  49.     tempOffset1 = localToGlobal->TransformPoint(ev, &tempOffset1);
  50.     SetOrigin(-tempOffset1.IntX(), -tempOffset1.IntY());
  51.  
  52.     // Set up special offset for later efficient reset of clipping region.
  53.     spclOffset = localToGlobal->GetQDOffset(ev);
  54.     ODTransform* contentTransform = facet->GetContentTransform(ev, 
  55.             kODNULL);
  56.     contentOffset = contentTransform->GetQDOffset(ev);
  57.     spclOffset.v -= contentOffset.v; spclOffset.h -= contentOffset.h;
  58.     localToGlobal->Release(ev);
  59.  
  60.     // Set up graphics port clipping.
  61.     RgnHandle saveClip = NewRgn();
  62.     GetClip(saveClip);
  63.     ODShape* clipShape = facet->GetAggregateClipShape(ev, kODNULL);
  64.     RgnHandle clip = clipShape->GetQDRegion(ev);
  65.     SetClip(clip);
  66.  
  67.     // Draw your controls (such as scroll bars) here, using the standard
  68.     // Toolbox calls. Remember to respect the scaling and rotation 
  69.     // information in your transform, or at least try to draw as best 
  70.     // you can, rather than simply signaling an error.
  71.     ...
  72.     
  73.     // Set up graphics port for drawing content.
  74.     ODPoint tempOffset2(0,0);
  75.     tempOffset2 = contentTransform->TransformPoint(ev, &tempOffset2);
  76.     SetOrigin(-tempOffset2.IntX(), -tempOffset2.IntY());
  77.     
  78.     // Use the special offset we set up earlier to keep the clip in the
  79.     // right place relative to the origin. Remember to remove the scroll
  80.     // bar area from the clipping region.
  81.     OffsetRgn(clip, spclOffset.h, spclOffset.v);
  82.     SetClip(clip);
  83.  
  84.     // And draw (insert your drawing code here).
  85.     // Remember to respect the scaling and rotation information
  86.     // in your content transform if possible, as mentioned above.
  87.     ...
  88.     
  89.     // Clean up.
  90.     SetClip(saveClip);
  91.     DisposeRgn(saveClip);
  92.     contentTransform->Release(ev);
  93.     clipShape->Release(ev);
  94.     SetOrigin(0, 0);
  95. }
  96.  
  97. // Listing 3. Handling the scrolling
  98. ODBoolean MyPart::HandleMouseDownScrollBar(Environment* ev, Point mouse, 
  99.         ODFrame* frame)
  100. {
  101.     ODSShort partcode = TrackControl(fScrollBar, mouse, kODNULL);
  102.     Point transPt;
  103.     ODSShort setting = GetControlValue(fScrollBar);
  104.  
  105.     if (partcode) {
  106.         // Deal with the scroll bar and choose the scroll distance.
  107.         switch (partcode) {
  108.             case inUpButton:
  109.                 setting--;
  110.                 break;
  111.             case inDownButton:
  112.                 setting++;
  113.                 break;
  114.             case inPageUp:
  115.                 if ((setting - kPBPageSize) < 0) setting = 0;
  116.                 else setting -= kPBPageSize;
  117.                 break;
  118.             case inPageDown:
  119.                 ODSShort max = GetControlMaximum(fScrollBar);
  120.                 if ((setting + kPBPageSize) > max) setting = max;
  121.                 else setting += kPBPageSize;
  122.                 break;
  123.             default:
  124.                 break;
  125.         }
  126.         
  127.         SetControlValue(fScrollBar, setting);
  128.         SetPt(&transPt, 0, (0-setting));        // This is a vertical
  129.                                                         // scroll bar.
  130.     
  131.         // Set up the transform.
  132.         ODTransform* newIntTrans = frame->CreateTransform(ev);
  133.         newIntTrans->SetQDOffset(ev, &transPt);
  134.         frame->ChangeInternalTransform(ev, newIntTrans, kODNULL);
  135.         newIntTrans->Release(ev);
  136.  
  137.         // Here's some simplified code for invalidating any embedded 
  138.         // facets that have been moved. This is a "saturation bombing"
  139.         // approach rather than the tuned code of a real application,
  140.         // but it gets the basic idea across. Typically, we do a
  141.         // ScrollRect followed by invalidation of the revealed area.
  142.         // Here we simply invalidate everything.
  143.         frame->Invalidate(ev, kODNULL, kODNULL);
  144.         return kODTrue;
  145.     }
  146.     return kODFalse;
  147. }
  148.  
  149.  
  150. // Listing 4. A 4x scaling operation
  151. void MyPart::ZoomContents4X(Environment* ev, ODFrame* frame)
  152. {
  153.     ODPoint        frameScale(4, 4);
  154.  
  155.     // Apply the zoom transformation.
  156.     ODTransform* intTrans = frame->GetInternalTransform(ev, kODNULL);
  157.     intTrans->ScaleBy(ev, &frameScale);
  158.     intTrans->Release(ev);
  159.  
  160.     // Invalidate the frame for redrawing.
  161.     frame->Invalidate(ev, kODNULL, kODNULL);
  162. }
  163.  
  164. // Listing 5. Making an embedded part visible
  165. void MyPart::EmbedPartFromSU(Environment* ev, ODStorageUnit* newSU, 
  166.         ODFacet* myFacet)
  167. {
  168.     ODPart* newPart = newSU->GetDraft(ev)->GetPart(ev, newPartID);
  169.     ODRect rect(0, 0, kPBDefaultFrameSize, kPBDefaultFrameSize);
  170.     ODShape* newFrameShape = myFacet->CreateShape(ev);
  171.     newFrameShape->SetRectangle(ev, &rect);
  172.     ODFrame* newFrame = newSU->GetDraft(ev)->CreateFrame(ev,
  173.             kODNULL,                         // Use the default frame type.
  174.             myFacet->GetFrame(ev),        // Containing frame is my frame.
  175.             newFrameShape,                    // Use the frame shape we set up.
  176.             (ODCanvas*)kODNULL,            // No special canvas.
  177.             newPart,                            // The part in the frame.
  178.             fSession->Tokenize(ev, kODViewAsFrame),    // View as a frame.
  179.             kODNullTypeToken,                // Undefined presentation.
  180.             kODFalse,                        // Not a root frame.
  181.             kODFalse);                        // Not overlaid.
  182.     newSU->Release(ev);
  183.     // Set up a clip shape, same as frame shape.
  184.     ODShape* frameShape = newFrame->GetFrameShape(ev, kODNULL);
  185.     ODShape* newClipShape = frameShape->Copy(ev);
  186.     Point offset = {100,100};
  187.     ODTransform* newExternalXForm = myFacet->CreateTransform(ev);
  188.     newExternalXForm->SetQDOffset(ev, &offset);
  189.     ODFacet* newFacet = myFacet->CreateEmbeddedFacet(ev,
  190.             newFrame,                 // Of this frame.
  191.             newClipShape,             // With this clip shape.
  192.             newExternalXForm,        // At this location/scale/rotation.
  193.             kODNULL,                    // No special canvas.
  194.             kODNULL,                    // No special bias canvas.
  195.             kODNULL,                    // No sibling specified.
  196.             kODFrameInFront);     // Put this facet at front.
  197.  
  198.     // At this point, we probably want to remember the new frame
  199.     // and facet in some data structure.
  200.     this->rememberFrame(newFrame, newFacet);
  201.  
  202.     // Invalidate facet so that it displays. We need to invalidate our 
  203.     // entire frame because the new facet may interact with other content 
  204.     // in various ways. This is the simplest correct method, although
  205.     // optimizations may be reasonable in production code.
  206.     myFacet->GetFrame(ev)->Invalidate(ev, kODNULL, kODNULL);
  207.  
  208.     // Clean up.
  209.     newPart->Release(ev);
  210.     newFrame->Release(ev);
  211.     newFrameShape->Release(ev);
  212.     newExternalXForm->Release(ev);
  213.     newClipShape->Release(ev);
  214.     frameShape->Release(ev);
  215. }
  216.  
  217.  
  218. // Listing 6. Altering the coordinate system scaling
  219. void MyPart::ShiftCoordinateScaling(Environment* ev, ODFrame* frame)
  220. {
  221.     ODPoint        frameScale(72,72);
  222.  
  223.     // Set up the transform.
  224.     ODTransform* existingTransform = frame->GetInternalTransform(ev,
  225.         kODNULL);
  226.     ODTransform* newIntTrans = existingTransform->Copy(ev);
  227.     existingTransform->Release(ev);
  228.     newIntTrans->ScaleDownBy(ev, &frameScale);
  229.         
  230.     // Apply the zoom transformation within myself.
  231.     frame->ChangeInternalTransform(ev, newIntTrans, kODNULL);
  232.     newIntTrans->Release(ev);
  233.  
  234.     // Now, be a good citizen and iterate over every facet of myself.
  235.     ODFrameFacetIterator* facets = frame->CreateFacetIterator(ev);
  236.     for (ODFacet* facet = facets->First(ev); facets->IsNotComplete(ev);
  237.             facet = facets->Next(ev)) {
  238.         // For each facet of myself, find every embedded facet.
  239.         ODFacetIterator* embeddedFacets = facet->CreateFacetIterator(ev,
  240.             kODTopDown, kODFrontToBack);
  241.         for (ODFacet* embeddedFacet = embeddedFacets->First(ev);
  242.                 embeddedFacets->IsNotComplete(ev);
  243.                 embeddedFacet = embeddedFacets->Next(ev)) {
  244.             // Alter the transform of each embedded facet.
  245.             existingTransform = embeddedFacet->GetExternalTransform(ev,
  246.                 kODNULL);
  247.             ODTransform* newExtTrans = existingTransform->Copy(ev);
  248.             // Notice that we scale in the opposite direction in 
  249.             // each embedded frame.
  250.             newExtTrans->ScaleBy(ev, &frameScale);
  251.             embeddedFacet->ChangeGeometry(ev, kODNULL, newExtTrans,
  252.                 kODNULL);
  253.             newExtTrans->Release(ev);
  254.             existingTransform->Release(ev);
  255.         }
  256.         ODDeleteObject(embeddedFacets);
  257.     }
  258.     ODDeleteObject(facets);
  259. }
  260.  
  261. // Listing 7. Setting clipping when printing to a PostScript device
  262. #define kPostScriptBegin    190    // Picture comments for PostScript 
  263. #define kPostScriptEnd        191    // printing.
  264. #define kPostScriptHandle    192
  265.  
  266. void ODBeginPostScriptClip(Environment* ev, ODShape *shape)
  267. {
  268.     ODPolygon poly = shape->CopyPolygon(ev);
  269.     Handle clipHandle = NewEmptyHandle();
  270.     
  271.     AppendString("\pgrestore", clipHandle);    // Utility routine to append
  272.     AppendString("\pnewpath", clipHandle);        // string to a handle.
  273.  
  274.     char buf[128];
  275.     ODContour *cont = poly.FirstContour();
  276.  
  277.     for (long n=poly.GetNContours(); n>0; n--) {
  278.         const ODPoint *v = cont->vertex;
  279.         long m = cont->nVertices;
  280.         if (m > 2) {
  281.             sprintf(buf, "%.2f %.2f moveto", v->x/65536.0, v->y/65536.0);
  282.             AppendBuf(buf, strlen(buf), clipHandle);    // Utility routine to 
  283.                                                 // append string buffer to a handle.
  284.             while (--m > 0) {
  285.                 v++;
  286.                 sprintf( buf, "%.2f %.2f lineto", v->x/65536.0,
  287.                     v->y/65536.0);
  288.                 AppendBuf(buf, strlen(buf), clipHandle);
  289.             }
  290.         }
  291.         AppendString("\pclosepath clip", clipHandle);
  292.         cont = cont->NextContour();
  293.     }
  294.     
  295.     // Set pic comment; then delete clipHandle.
  296.     AppendString("\pgsave", clipHandle);
  297.     PicComment(kPostScriptBegin, 0, kODNULL);
  298.     PicComment(kPostScriptHandle, GetHandleSize(clipHandle), clipHandle);
  299.     PicComment(kPostScriptEnd, 0, kODNULL);
  300.     DisposeHandle(clipHandle);
  301. }
  302.  
  303. void ODEndPostScriptClip( )
  304. {
  305.     Handle clipHandle = NewEmptyHandle();
  306.     AppendString("\pgrestore", clipHandle);
  307.     PicComment(kPostScriptBegin, 0, kODNULL);
  308.     PicComment(kPostScriptHandle, GetHandleSize(clipHandle), clipHandle);
  309.     PicComment(kPostScriptEnd, 0, kODNULL);
  310.     DisposeHandle(clipHandle);
  311. }
  312.  
  313. // Listing 8. Setup for basic printing
  314. ODFacet* MyPart::BeginPrinting(Environment *ev, ODFrame* rootFrame,
  315.         TPrPort* thePrPort, ODRect *pageRect)
  316. {
  317.     // Set up identity transform, get page rect, set up to clip to it.
  318.     ODTransform* xtransform = rootFrame->CreateTransform(ev);
  319.     ODShape* clipshape = rootFrame->CreateShape(ev);
  320.     clipshape->SetRectangle(ev, pageRect);
  321.  
  322.     // Create a facet with the specific geometry we just set up.
  323.     ODFacet* prFacet = fSession->GetWindowState(ev)->
  324.             CreateFacet(ev, rootFrame, clipshape, xtransform, kODNULL, 
  325.             kODNULL);
  326.     xtransform->Release(ev);
  327.     clipshape->Release(ev);
  328.  
  329.     // Set up a canvas based on the print job's port.
  330.     ODCanvas* prCanvas = prFacet->CreateCanvas(ev, kODQuickDraw,
  331.             (GrafPtr)thePrPort, kODFalse, kODFalse);
  332.     prCanvas->SetPlatformPrintJob(ev, kODQuickDraw, (GrafPtr)thePrPort);
  333.     
  334.     // Make it the canvas of the facet we created.
  335.     prFacet->SetCanvas(ev, prCanvas);
  336.     rootFrame->FacetAdded(ev, prFacet);
  337.     
  338.     // Return the facet to the main print routine.
  339.     return prFacet;
  340. }
  341.  
  342. // Listing 9. Printing a page
  343. void MyPart::PrintPage(Environment *ev, ODFacet* prFacet, ODUShort page,
  344.     ODRect *pageRect)
  345. {
  346.     // Get some basic printing geometry.
  347.     ODRect    bbox;
  348.     Rect        frect, qdPRect;
  349.     
  350.     ODShape* frameShape = prFacet->GetFrame(ev)->
  351.             GetFrameShape(ev, kODNULL);
  352.     frameShape->GetBoundingBox(ev, &bbox);
  353.     bbox.AsQDRect(frect);
  354.     frameShape->Release(ev);
  355.     Point pt = {0,0};
  356.     ODUShort locator = page-1;
  357.     
  358.     // Pick an appropriate offset, based on page number.
  359.     pageRect->AsQDRect(qdPRect);
  360.     while (locator) {
  361.         pt.v += (qdPRect.bottom+1);
  362.         locator--;
  363.         if (PtInRect(pt, &frect))
  364.             continue;
  365.         else {
  366.             pt.v = 0; pt.h += (qdPRect.right+1);
  367.         }
  368.     }
  369.     
  370.     // Make a transform for that offset.
  371.     ODTransform* xtransform = prFacet->CreateTransform(ev);
  372.     xtransform->SetQDOffset(ev, &pt);
  373.  
  374.     // Create a clip shape for the page, based on the transform.
  375.     ODShape* clipshape = prFacet->CreateShape(ev);
  376.     clipshape->SetRectangle(ev, pageRect);
  377.     ODShape* invalshape = clipshape->Copy(ev);
  378.     clipshape->Transform(ev, xtransform);
  379.     xtransform->Invert(ev);
  380.  
  381.     // Change the geometry of the printing facet.
  382.     prFacet->ChangeGeometry(ev, clipshape, xtransform, kODNULL);
  383.     
  384.     // Draw everything on the page. OpenDoc will call the Draw method
  385.     // on every part visible on the page.
  386.     prFacet->Update(ev, invalshape, kODNULL);
  387.  
  388.     // Clean up.
  389.     clipshape->Release(ev);
  390.     invalshape->Release(ev);
  391.     xtransform->Release(ev);
  392. }
  393.  
  394. // Listing 10. Cleanup after printing
  395. void MyPart::EndPrinting(Environment *ev, ODFacet* prFacet)
  396. {
  397.     // Find the printing canvas and facet; delete them.
  398.     ODCanvas* prCanvas = prFacet->GetCanvas(ev);
  399.     prFacet->GetFrame(ev)->FacetRemoved(ev, prFacet);
  400.     delete prCanvas;
  401.     delete prFacet;
  402. }